﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Practices.Prism.Regions;
using Xceed.Wpf.AvalonDock;
using Xceed.Wpf.AvalonDock.Layout;
using Hopscotch.Presentation.Common;

namespace Hopscotch.Application.Shell.Utils
{
    //ZXZX: This does not dispose views when they are closed...
    //http://avalondock.codeplex.com/discussions/390255
    public class AvalonDockRegionAdapter : RegionAdapterBase<DockingManager>
    {
        public AvalonDockRegionAdapter(IRegionBehaviorFactory factory)
            : base(factory)
        {
        }

        protected override IRegion CreateRegion()
        {
            return new AllActiveRegion();
        }

        protected override void Adapt(IRegion region, DockingManager regionTarget)
        {
            region.Views.CollectionChanged += delegate(
                Object sender, NotifyCollectionChangedEventArgs e)
            {
                this.OnViewsCollectionChanged(sender, e, region, regionTarget);
            };
            regionTarget.DocumentClosed += delegate(
                            Object sender, DocumentClosedEventArgs e)
            {
                this.OnDocumentClosedEventArgs(sender, e, region);
            };
        }

        /// <summary>
        /// Handles the NotifyCollectionChangedEventArgs event.
        /// </summary>
        void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, DockingManager regionTarget)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (FrameworkElement item in e.NewItems)
                {
                    UIElement view = item as UIElement;

                    if (view != null)
                    {
                        //Create a new layout document to be included in the LayoutAnchorablePane (defined in xaml)
                        LayoutAnchorable newLayoutAnchorable = new LayoutAnchorable();
                        //Set the content of the LayoutAnchorable
                        newLayoutAnchorable.Content = item;

                        ViewModelBase viewModel = item.DataContext as ViewModelBase;

                        if (viewModel != null)
                        {
                            newLayoutAnchorable.Title = viewModel.ViewTitle;
                            if (viewModel.Icon16Uri != null)
                                newLayoutAnchorable.IconSource = new BitmapImage(viewModel.Icon16Uri);
                        }
                        else
                        {
                            newLayoutAnchorable.Title = "Tool";
                        }

                        //Store all LayoutAnchorables already pertaining to the LayoutAnchorablePane (defined in xaml)
                        List<LayoutAnchorable> oldLayoutAnchorables = new List<LayoutAnchorable>();
                        //Get the current ILayoutAnchorablePane ... Depending on the arrangement of the views this can be either 
                        //a simple LayoutAnchorablePane or a LayoutAnchorablePaneGroup
                        ILayoutAnchorablePane currentILayoutAnchorablePane = (ILayoutAnchorablePane)regionTarget.Layout.RootPanel.Children[0];

                        if (currentILayoutAnchorablePane.GetType() == typeof(LayoutAnchorablePaneGroup))
                        {
                            //If the current ILayoutAnchorablePane turns out to be a group
                            //Get the children (LayoutAnchorables) of the first pane
                            LayoutAnchorablePane oldLayoutAnchorablePane = (LayoutAnchorablePane)currentILayoutAnchorablePane.Children.ToList()[0];
                            foreach (LayoutAnchorable child in oldLayoutAnchorablePane.Children)
                            {
                                oldLayoutAnchorables.Insert(0, child);
                            }
                        }
                        else if (currentILayoutAnchorablePane.GetType() == typeof(LayoutAnchorablePane))
                        {
                            //If the current ILayoutAnchorablePane turns out to be a simple pane
                            //Get the children (LayoutAnchorables) of the single existing pane.
                            foreach (LayoutAnchorable child in currentILayoutAnchorablePane.Children)
                            {
                                oldLayoutAnchorables.Insert(0, child);
                            }
                        }

                        //Create a new LayoutAnchorablePane and inserts your new LayoutAnchorable
                        LayoutAnchorablePane newLayoutAnchorablePane = new LayoutAnchorablePane();
                        newLayoutAnchorablePane.InsertChildAt(0, newLayoutAnchorable);

                        //Append to the new LayoutAnchorablePane the old LayoutAnchorables
                        foreach (LayoutAnchorable doc in oldLayoutAnchorables)
                        {
                            newLayoutAnchorablePane.InsertChildAt(0, doc);
                        }

                        //Traverse the visual tree of the xaml and replace the LayoutAnchorablePane (or LayoutAnchorablePaneGroup) in xaml
                        //with your new LayoutAnchorablePane (or LayoutAnchorablePaneGroup)
                        if (currentILayoutAnchorablePane.GetType() == typeof(LayoutAnchorablePane))
                            regionTarget.Layout.RootPanel.ReplaceChildAt(0, newLayoutAnchorablePane);
                        else if (currentILayoutAnchorablePane.GetType() == typeof(LayoutAnchorablePaneGroup))
                        {
                            currentILayoutAnchorablePane.ReplaceChild(currentILayoutAnchorablePane.Children.ToList()[0], newLayoutAnchorablePane);
                            regionTarget.Layout.RootPanel.ReplaceChildAt(0, currentILayoutAnchorablePane);
                        }
                        newLayoutAnchorable.IsActive = true;
                    }
                }
            }
        }

        /// <summary>
        /// Handles the DocumentClosedEventArgs event raised by the DockingNanager when
        /// one of the LayoutContent it hosts is closed.
        /// </summary>
        void OnDocumentClosedEventArgs(object sender, DocumentClosedEventArgs e, IRegion region)
        {
            region.Remove(e.Document.Content);
        }

    }
}
